package com.ruoyi.mentor.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.ExamineStatusConstants;
import com.ruoyi.common.constant.UserTypeConstants;
import com.ruoyi.common.core.page.PagePlus;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.mentor.bo.*;
import com.ruoyi.mentor.domain.*;
import com.ruoyi.mentor.mapper.InstructorMapper;
import com.ruoyi.mentor.service.IInstructorService;
import com.ruoyi.mentor.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 导师Service业务层处理
 *
 * @author LH
 * @date 2021-05-21
 */
@Service
public class InstructorServiceImpl extends ServiceImpl<InstructorMapper, Instructor> implements IInstructorService {

    @Autowired
    InsPaperServiceImpl insPaperService;

    @Autowired
    InsProjectServiceImpl insProjectService;

    @Autowired
    SpotServiceImpl spotService;

    @Autowired
    ChooseServiceImpl chooseService;

    @Autowired
    InsDetailServiceImpl insDetailService;

    @Autowired
    ExamineServiceImpl examineService;

    @Autowired
    SubjectServiceImpl subjectService;

    @Autowired
    UpdatePasswordServiceImpl updatePasswordService;

    @Override
    public InstructorVo queryById(Long id){
        return getVoById(id, InstructorVo.class);
    }

    @Override
    public TableDataInfo<InstructorVo> queryPageList(InstructorQueryBo bo) {
        PagePlus<Instructor, InstructorVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), InstructorVo.class);
        return PageUtils.buildDataInfo(result);
    }

    @Override
    public List<ImportInstructorVo> queryList(InstructorQueryBo bo) {
        List<ImportInstructorVo> collect = listVo(buildQueryWrapper(bo), InstructorVo.class).stream().map(item -> {
            ImportInstructorVo instructorVo = new ImportInstructorVo();
            Long insId = item.getId();
            InsDetail insDetail = insDetailService.getOne(new QueryWrapper<InsDetail>().eq("ins_id", insId));
            if (insDetail!=null){
                BeanUtils.copyProperties(insDetail, instructorVo);
            }
            BeanUtils.copyProperties(item, instructorVo);
            return instructorVo;
        }).collect(Collectors.toList());
        return collect;
    }

    private LambdaQueryWrapper<Instructor> buildQueryWrapper(InstructorQueryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<Instructor> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getExamineStatus()!=null,Instructor::getExamineStatus,bo.getExamineStatus());
        lqw.eq(StrUtil.isNotBlank(bo.getInsCartId()), Instructor::getInsCartId, bo.getInsCartId());
        lqw.like(StrUtil.isNotBlank(bo.getInsName()), Instructor::getInsName, bo.getInsName());
        lqw.eq(bo.getInsGender()!=null, Instructor::getInsGender, bo.getInsGender());
        lqw.eq(StrUtil.isNotBlank(bo.getInsProfessor()), Instructor::getInsProfessor, bo.getInsProfessor());
        lqw.eq(StrUtil.isNotBlank(bo.getInsCommander()), Instructor::getInsCommander, bo.getInsCommander());
        lqw.eq(StrUtil.isNotBlank(bo.getInsMobile()), Instructor::getInsMobile, bo.getInsMobile());
        lqw.eq(StrUtil.isNotBlank(bo.getInsPhone()), Instructor::getInsPhone, bo.getInsPhone());
        lqw.eq(StrUtil.isNotBlank(bo.getInsEmail()), Instructor::getInsEmail, bo.getInsEmail());
        return lqw;
    }

    private LambdaQueryWrapper<Instructor> buildQueryWrapper(StudentSelectInstructorBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<Instructor> lqw = Wrappers.lambdaQuery();
        //必须是通过审核的老师
        lqw.eq(Instructor::getExamineStatus,ExamineStatusConstants.EXAMINE_SUCCESS);
        lqw.eq(bo.getInsGender()!=null, Instructor::getInsGender, bo.getInsGender());
        lqw.like(StrUtil.isNotBlank(bo.getInsName()), Instructor::getInsName, bo.getInsName());
        return lqw;
    }


    @Override
    public Boolean insertByAddBo(InstructorAddBo bo) {
        Instructor add = BeanUtil.toBean(bo, Instructor.class);
        validEntityBeforeSave(add);
        return save(add);
    }

    @Override
    public Boolean updateByEditBo(InstructorEditBo bo) {
        Instructor update = BeanUtil.toBean(bo, Instructor.class);
        validEntityBeforeSave(update);
        return updateById(update);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(Instructor entity){
        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return removeByIds(ids);
    }

    //保存详细信息
    @Transactional
    @Override
    public void saveInstructorDetail(InstructorDetailVo instructorDetailVo) {

        if (instructorDetailVo.getInsId()==null){
            //新增
            Instructor instructor = new Instructor();
            InsDetail insDetail = new InsDetail();
            BeanUtils.copyProperties(instructorDetailVo,instructor);
            instructor.setExamineStatus(ExamineStatusConstants.EXAMINE_ING);
            save(instructor);

            //设置详细信息
            insDetail.setInsId(instructorDetailVo.getInsId());
            BeanUtil.copyProperties(instructorDetailVo,insDetail);


            String papersStr = instructorDetailVo.getInsPapers();
            if (papersStr!=null&&papersStr.length()>0){
                InsPaper insPaper = new InsPaper();
                insPaper.setDetail(papersStr);
                insPaper.setInsId(instructorDetailVo.getInsId());
                insPaperService.save(insPaper);
            }
            String projectsStr = instructorDetailVo.getInsProjects();
            if (projectsStr!=null&&projectsStr.length()>0){
                InsProject insProject = new InsProject();
                insProject.setDetail(projectsStr);
                insProject.setInsId(instructorDetailVo.getInsId());
                insProjectService.save(insProject);
            }

        }else {
            //修改
            Instructor instructor = new Instructor();
            BeanUtils.copyProperties(instructorDetailVo,instructor);
            instructor.setId(instructorDetailVo.getInsId());
            instructor.setExamineStatus(ExamineStatusConstants.EXAMINE_ING);
            updateById(instructor);

            //修改详细信息
            InsDetail insDetail = insDetailService.getOne(new QueryWrapper<InsDetail>().eq("ins_id", instructor.getId()));
            if (insDetail==null){
                insDetail = new InsDetail();
            }
            insDetail.setInsId(instructor.getId());
            BeanUtil.copyProperties(instructorDetailVo,insDetail);
            insDetailService.saveOrUpdate(insDetail);


            insPaperService.remove(new QueryWrapper<InsPaper>().eq("ins_id",instructor.getId()));
            insProjectService.remove(new QueryWrapper<InsProject>().eq("ins_id",instructor.getId()));


            String papersStr = instructorDetailVo.getInsPapers();
            if (papersStr!=null&&papersStr.length()>0){
                InsPaper insPaper = new InsPaper();
                insPaper.setDetail(papersStr);
                insPaper.setInsId(instructorDetailVo.getInsId());
                insPaperService.save(insPaper);
            }
            String projectsStr = instructorDetailVo.getInsProjects();
            if (projectsStr!=null&&projectsStr.length()>0){
                InsProject insProject = new InsProject();
                insProject.setDetail(projectsStr);
                insProject.setInsId(instructorDetailVo.getInsId());
                insProjectService.save(insProject);
            }

        }


    }

    /**
     * 根据用户id获取详细信息
     * @param userId
     * @return
     */
    @Override
    public InstructorDetailVo getInstructorDetailByUserId(Long userId) {

        InstructorDetailVo res = new InstructorDetailVo();

        Instructor instructor = getOne(new QueryWrapper<Instructor>().eq("user_id", userId));
        if (instructor==null){
            return res;
        }

        Long insId = instructor.getId();
        BeanUtils.copyProperties(instructor,res);


        res.setUserId(userId);
        res.setInsId(insId);
        InsDetail insDetail = insDetailService.getOne(new QueryWrapper<InsDetail>().eq("ins_id", insId));

        if (insDetail!=null){
            BeanUtil.copyProperties(insDetail,res);
        }


        InsPaper insPapers = insPaperService.getOne(new QueryWrapper<InsPaper>().eq("ins_id", instructor.getId()));
        InsProject insProjects = insProjectService.getOne(new QueryWrapper<InsProject>().eq("ins_id", instructor.getId()));
        if (insPapers!=null){
            res.setInsPapers(insPapers.getDetail());
        }

        if (insProjects!=null){
            res.setInsProjects(insProjects.getDetail());
        }
        return res;
    }

    /**
     * 根据id获取详细信息
     * @param insId
     * @return
     */
    @Override
    public InstructorDetailVo getInstructorDetailById(Long insId) {

        InstructorDetailVo res = new InstructorDetailVo();

        Instructor instructor = getById(insId);
        if (instructor==null){
            throw new CustomException("获取导师信息出错");
        }
        BeanUtils.copyProperties(instructor,res);
        res.setInsId(instructor.getId());


        InsDetail insDetail = insDetailService.getOne(new QueryWrapper<InsDetail>().eq("ins_id", insId));

        if (insDetail!=null){
            BeanUtil.copyProperties(insDetail,res);
        }

        InsPaper insPapers = insPaperService.getOne(new QueryWrapper<InsPaper>().eq("ins_id", instructor.getId()));
        InsProject insProjects = insProjectService.getOne(new QueryWrapper<InsProject>().eq("ins_id", instructor.getId()));

        if(insPapers!=null){
            res.setInsPapers(insPapers.getDetail());
        }
        if(insProjects!=null){
            res.setInsProjects(insProjects.getDetail());
        }
        return res;
    }

    /**
     * 获取以及审核过的导师
     * @param bo
     * @return
     */
    @Override
    public TableDataInfo<InstructorVo> getAcceptedInstructorList(StudentSelectInstructorBo bo) {
        Subject subject = subjectService.getById(bo.getSubId());
        if(subject==null){
            throw new CustomException("未找到该学科");
        }
        PagePlus<Instructor, InstructorVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), InstructorVo.class);
        List<InstructorVo> collect = result.getRecordsVo().stream().filter(item -> {

            /**学生只能选择本专业的导师*/
            if (!subject.getSubName().equals("不区分研究方向")){
                Long insId = item.getId();
                //查询导师招生表
                //获取最近一年的该专业的招生名额表
                Spot spot = spotService.getLastSpot(insId,bo.getSubId());
                if (spot == null){
                    //该导师没有招生
                    return false;
                }else {
                    InstructorVo.SubVo subVo = new InstructorVo.SubVo();
                    BeanUtils.copyProperties(subject,subVo);
                    subVo.setCheckedNumber(spot.getCheckedNumber());
                    subVo.setPgNumber(spot.getPgNumber());
                    item.setSubs(Arrays.asList(subVo));
                    item.setCheckedNumber(spot.getCheckedNumber());
                    item.setNumber(spot.getPgNumber());
                    return true;
                }
            }else {
                //获取该导师的所有招生信息
                List<InstructorVo.SubVo> subjectList = spotService.getSubjectList(item.getId());
                if (subjectList==null||subjectList.size()==0){
                    return false;
                }else {
                    item.setSubs(subjectList);
                    return true;
                }
            }

        }).filter(item->{
            //查询是否已经选择了该导师
            int count = chooseService.count(new QueryWrapper<Choose>().eq("ins_id", item.getId()).eq("stu_id", bo.getStuId()));
            if (count>0){
                return false;
            }else {
                return true;
            }
        }).collect(Collectors.toList());

        result.setRecordsVo(collect);
        return PageUtils.buildDataInfo(result);
    }

    /**
     * 根据用户id删除所有导师信息
     *
     * @param userId
     */
    @Override
    @Transactional
    public void removeInstructorByUserId(Long userId) {
        Instructor instructor = getOne(new QueryWrapper<Instructor>().eq("user_id", userId));
        if (instructor!=null){
            insDetailService.remove(new QueryWrapper<InsDetail>().eq("ins_id",instructor.getId()));
            insPaperService.remove(new QueryWrapper<InsPaper>().eq("ins_id",instructor.getId()));
            insProjectService.remove(new QueryWrapper<InsProject>().eq("ins_id",instructor.getId()));
            examineService.remove(new QueryWrapper<Examine>().eq("si_id",instructor.getId()).eq("user_type", UserTypeConstants.ROLE_INSTRUCTOR));
            chooseService.remove(new QueryWrapper<Choose>().eq("ins_id",instructor.getId()));
            spotService.remove(new QueryWrapper<Spot>().eq("ins_id",instructor.getId()));
            updatePasswordService.remove(new QueryWrapper<UpdatePassword>().eq("user_id",userId));
            removeById(instructor);
        }

    }

    /**
     * 获取招生未招满的导师
     *
     * @return
     */
    @Override
    public List<NotFullInstructorVo> selectNotFull() {
        List<NotFullInstructorVo> res = new ArrayList<>();
        List<Map<String, Object>> spots = spotService.getNotFullSpot();
        for (Map<String, Object> spotMap : spots) {

            NotFullInstructorVo notFullInstructorVo = new NotFullInstructorVo();

            Long insId = (Long) spotMap.get("insId");
            String[] subIds = ((String) spotMap.get("subIds")).split(",");
            String[] checkedNumbers = ((String)spotMap.get("checkedNumbers")).split(",");
            String[] pgNumbers = ((String)spotMap.get("pgNumbers")).split(",");
            String[] spotIds = ((String)spotMap.get("spotIds")).split(",");
            Instructor instructor = getById(insId);
            notFullInstructorVo.setInsId(insId);
            notFullInstructorVo.setInsName(instructor.getInsName());
            List<NotFullInstructorVo.SpotChildren> spotChildren = new ArrayList<>();
            for (int i = 0; i < subIds.length; i++) {
                NotFullInstructorVo.SpotChildren spotChild = new NotFullInstructorVo.SpotChildren();
                Subject subject = subjectService.getById(subIds[i]);
                spotChild.setSubId(Long.parseLong(subIds[i]));
                spotChild.setSubName(subject.getSubName());
                spotChild.setSpotId(Long.parseLong(spotIds[i]));
                spotChild.setCheckedNumber(Long.parseLong(checkedNumbers[i]));
                spotChild.setPgNumber(Long.parseLong(pgNumbers[i]));
                spotChildren.add(spotChild);
            }
            notFullInstructorVo.setChildren(spotChildren);
            res.add(notFullInstructorVo);
        }
        return res;
    }

}
